/********************************************************/
/*	Copyright (C) 2012 Gong Li Bin			*/
/*	Project:	MrCloud(MapReduce)		*/
/*	Author:		gong_libin			*/
/*	Date:		2013_07_11			*/
/*	File:		MrMonitor.cpp			*/
/********************************************************/

#include "MrMonitor.h"

bool g_bDebug = false;

int main(int argc, char* argv[])
{
	pid_t iPid = 0;
	int iIndex = 0;
	int iReturn = 0;
	MRMNCONF_S stConf;
	char szConf[MR_VALUE] = "MrMonitor.conf";

	struct option stOptions[] = {
		{"conf", 1, 0, 'c'},
		{"debug", 0, 0, 'd'},
		{"help", 0, 0, 'h'},
		{"version", 0, 0, 'v'},
		{0, 0, 0, 0},
	};

	while (true) {
		iReturn = getopt_long(argc, argv, "c:dhv", stOptions, &iIndex);
		if (iReturn < 0) {
			break;
		}
		switch (iReturn) {
			case 'c':
				strncpy(szConf, optarg, MR_VALUE);
				break;
			case 'd':
				g_bDebug = true;
				break;
			case 'h':
				MrMnHelp(argv[0]);
				return MR_SUCCESS;
			case 'v':
				MR_PRINT("Copyright (C) 2012 Mrar Technology Inc.\n");
				MR_PRINT("%s Build on %s %s.\n", MR_MN_VERSION, __DATE__, __TIME__);
				return MR_SUCCESS;
			default:
				return MR_SUCCESS;
		}
	}

	if (MR_SUCCESS == MrMnInit(szConf, &stConf)) {
		if (true == g_bDebug) {
			MR_DEBUG("Tim: %s\n", stConf.m_szTim);
			MR_DEBUG("Cmd: %s\n", stConf.m_szCmd);
			MR_DEBUG("Log: %s\n", stConf.m_szLog);
			MrMnProc(stConf.m_CProc);
		}
	}
	else {
		MR_ERROR("Failed to MrMnInit\n");
		return MR_FAILURE;
	}

	if (true != g_bDebug) {
		MrFork();
	}

	while (true) {
		iPid = fork();
		switch (iPid) {
			case MR_SUCCESS:
				/* child */
				MrMnRun(&stConf);
				exit(MR_SUCCESS);
				break;
			case MR_FAILURE:
				/* error */
				MR_ERROR("%s\n", strerror(errno));
				break;
			default:
				/* parent */
				waitpid(iPid, NULL, 0);
				break;
		}
		sleep(atoi(stConf.m_szTim));
	}

	return MR_SUCCESS;
}

void MrMnHelp(char* pszProc)
{
	MR_PRINT("Usage: %s [options]\n", pszProc);
	MR_PRINT("Valid options are:\n");
	MR_PRINT("[*] -c or --conf:       set configure.\n");
	MR_PRINT("[0] -d or --debug:      set debug mode.\n");
	MR_PRINT("[0] -h or --help:       show help.\n");
	MR_PRINT("[0] -v or --version:    show version.\n");
	MR_PRINT("Copyright (C) 2012 Mrar Technology Inc.\n");
	MR_PRINT("%s Build on %s %s.\n", MR_MN_VERSION, __DATE__, __TIME__);

	return;
}

int MrMnInit(char* pszConf, MRMNCONF_S* pstConf)
{
	CMrConf CConf;
	char* pszProc = NULL;
	int iReturn = MR_SUCCESS;

	if (MR_SUCCESS == CConf.MrConfOpen(pszConf)) {
		/* tim */
		memset(pstConf->m_szTim, '\0', MR_VALUE);
		if (MR_SUCCESS != CConf.MrConfGetVal((char*)"TIM", (char*)"TIM", pstConf->m_szTim)) {
			iReturn = MR_FAILURE;
		}
		/* cmd */
		memset(pstConf->m_szCmd, '\0', MR_VALUE);
		if (MR_SUCCESS != CConf.MrConfGetVal((char*)"CMD", (char*)"CMD", pstConf->m_szCmd)) {
			iReturn = MR_FAILURE;
		}
		/* log */
		memset(pstConf->m_szLog, '\0', MR_VALUE);
		if (MR_SUCCESS != CConf.MrConfGetVal((char*)"LOG", (char*)"LOG", pstConf->m_szLog)) {
			iReturn = MR_FAILURE;
		}
		/* pro */
		if (MR_SUCCESS == CConf.MrConfGetSec((char*)"PROC")) {
			if (MR_SUCCESS == pstConf->m_CProc.MrSetInit(MR_MN_PROC, sizeof(char**))) {
				while (true) {
					if (NULL != (pszProc = (char*)MrMalloc(sizeof(UCHAR) * MR_PACKET))) {
						if (MR_SUCCESS == CConf.MrConfGetLine(pszProc, MR_PACKET)) {
							if (true == CConf.MrConfIsValid(pszProc)) {
								CConf.MrConfTrim(pszProc);
								pstConf->m_CProc.MrSetIndexPut(pstConf->m_CProc.MrSetGetCount(), &pszProc);
							}
						}
						else {
							break;
						}
					}
					else {
						iReturn = MR_FAILURE;
						break;
					}
				}
			}
			else {
				iReturn = MR_FAILURE;
			}
		}
		else {
			iReturn = MR_FAILURE;
		}
		CConf.MrConfClose();
	}
	else {
		iReturn = MR_FAILURE;
	}

	return iReturn;
}

void MrMnProc(CMrSet& CProc)
{
	UINT uiCount = 0;

	for (; uiCount < CProc.MrSetGetCount(); uiCount ++) {
		MR_PRINT("Proc[%04d]: %s\n", uiCount + 1, *(char**)CProc.MrSetIndexGet(uiCount));
	}

	return;
}

void MrMnLog(char* pszFile, char* pszLog)
{
	CMrLog CLog;
	char szTime[MR_DAYTIME] = { 0 };

	if (MR_SUCCESS == CLog.MrLogOpen(pszFile, (char*)"a")) {
		MrLocalDayTime(szTime);
		strcpy(szTime + strlen(szTime), "\n");
		CLog.MrLogWrite(szTime, strlen(szTime));
		CLog.MrLogWrite(pszLog, strlen(pszLog));
		CLog.MrLogClose();
	}

	return;
}

void MrMnRun(MRMNCONF_S* pstConf)
{
	CMrPipe CPipe;
	UINT uiCount = 0;
	char szLog[MR_BIGPACKET] = { 0 };

	if (MR_SUCCESS == CPipe.MrPipeOpen(pstConf->m_szCmd, (char*)"r")) {
		if (MR_SUCCESS == CPipe.MrPipeResultMalloc(MR_PIPE)) {
			if (CPipe.MrPipeRead(MR_PIPE) > 0) {
				if (true == g_bDebug) {
					MR_DEBUG("Result:\n%s\n", CPipe.MrPipeResultGet());
				}
				for (; uiCount < pstConf->m_CProc.MrSetGetCount(); uiCount ++) {
					if (NULL == strstr(CPipe.MrPipeResultGet(), *(char**)pstConf->m_CProc.MrSetIndexGet(uiCount))) {
						if (true == g_bDebug) {
							MR_DEBUG("\"%s\" be restarted\n", *(char**)pstConf->m_CProc.MrSetIndexGet(uiCount));
						}
						sprintf(szLog + strlen(szLog), "Start %s\n", *(char**)pstConf->m_CProc.MrSetIndexGet(uiCount));
						system(*(char**)pstConf->m_CProc.MrSetIndexGet(uiCount));
					}
				}
			}
			else {
				strcpy(szLog + strlen(szLog), "Failed to MrPipeRead\n");
			}
			CPipe.MrPipeResultFree();
		}
		else {
			strcpy(szLog + strlen(szLog), "Failed to MrPipeResultMalloc\n");
		}
		CPipe.MrPipeClose();
	}
	else {
		strcpy(szLog + strlen(szLog), "Failed to MrPipeOpen\n");
	}

	if (strlen(szLog) > 0) {
		MrMnLog(pstConf->m_szLog, szLog);
	}

	return;
}
